

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
  <link rel="icon" href="/img/fluid.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="John Doe">
  <meta name="keywords" content="">
  
    <meta name="description" content="“ 常在河边走，哪能不湿鞋。” ——若发现文章内容有误，敬请指正，望不吝赐教，谢谢!  @[toc] 参考资料  视频链接1 视频链接2  运行环境  Windows10 Maven 3.8.3 IDEA 2021.1 专业版 JDK 8 SpringBoot 2.6  Shrio 1.8  一、Shiro体系结构  Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权">
<meta property="og:type" content="article">
<meta property="og:title" content="Shiro 笔记1 Shrio体系结构 MDK5 + salt 加密案例 SpringBoot整合Shiro+SSM+Thymeleaf案例">
<meta property="og:url" content="http://example.com/2022/02/08/Shiro%20%E7%AC%94%E8%AE%B01%20Shrio%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84%20MDK5%20+%20salt%20%E5%8A%A0%E5%AF%86%E6%A1%88%E4%BE%8B%20SpringBoot%E6%95%B4%E5%90%88Shiro+SSM+Thymeleaf%E6%A1%88%E4%BE%8B/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="“ 常在河边走，哪能不湿鞋。” ——若发现文章内容有误，敬请指正，望不吝赐教，谢谢!  @[toc] 参考资料  视频链接1 视频链接2  运行环境  Windows10 Maven 3.8.3 IDEA 2021.1 专业版 JDK 8 SpringBoot 2.6  Shrio 1.8  一、Shiro体系结构  Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://img-blog.csdnimg.cn/b80e05d0cacf4a6bbfc9021636a3c36e.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/8b98d70269ab4488897c3fc637647e73.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/26796868b61f40deac3baa4803c29c14.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/95847210cb16462a9a890bf920a52b38.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/ad743a6f11c74b9d978a8a4a137a1912.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/a42e7d1c0e7d4ff9b1b3375a0a954226.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/70c93e12581140cd8e9f53f53dcdce10.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/56a440463fac4d26a71aad0e39d29bfc.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/2c6314af180d4b34ad448877c6c903fc.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/3b09109466df4895aff090c4355343f0.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/4b440493c2c44d368047a855389a93b2.png">
<meta property="article:published_time" content="2022-02-08T11:45:34.000Z">
<meta property="article:modified_time" content="2022-08-22T15:48:07.358Z">
<meta property="article:author" content="John Doe">
<meta property="article:tag" content="Shiro">
<meta property="article:tag" content="SpringBoot">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://img-blog.csdnimg.cn/b80e05d0cacf4a6bbfc9021636a3c36e.png">
  
  
  
  <title>Shiro 笔记1 Shrio体系结构 MDK5 + salt 加密案例 SpringBoot整合Shiro+SSM+Thymeleaf案例 - Hexo</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.9.2","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.2.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>尤 Ni&#39;s Blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="Shiro 笔记1 Shrio体系结构 MDK5 + salt 加密案例 SpringBoot整合Shiro+SSM+Thymeleaf案例"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        John Doe
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-02-08 19:45" pubdate>
          2022年2月8日 晚上
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          37k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          312 分钟
        
      </span>
    

    
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Shiro 笔记1 Shrio体系结构 MDK5 + salt 加密案例 SpringBoot整合Shiro+SSM+Thymeleaf案例</h1>
            
              <p class="note note-info">
                
                  
                    本文最后更新于：1 小时前
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <blockquote>
<p>“ 常在河边走，哪能不湿鞋。” ——若发现文章内容有误，敬请指正，望不吝赐教，谢谢!</p>
</blockquote>
<p>@[toc]</p>
<h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><hr>
<ul>
<li><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1NE411i7S8?p=8">视频链接1</a></li>
<li><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1uz4y197Zm?p=8">视频链接2</a></li>
</ul>
<h1 id="运行环境"><a href="#运行环境" class="headerlink" title="运行环境"></a>运行环境</h1><hr>
<ul>
<li>Windows10</li>
<li>Maven 3.8.3</li>
<li>IDEA 2021.1 专业版</li>
<li>JDK 8</li>
<li>SpringBoot 2.6 </li>
<li>Shrio 1.8</li>
</ul>
<h1 id="一、Shiro体系结构"><a href="#一、Shiro体系结构" class="headerlink" title="一、Shiro体系结构"></a>一、Shiro体系结构</h1><hr>
<blockquote>
<p>Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。</p>
</blockquote>
<p><img src="https://img-blog.csdnimg.cn/b80e05d0cacf4a6bbfc9021636a3c36e.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<table>
<thead>
<tr>
<th align="left">模块</th>
<th align="left">描述</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>Authentication</code></td>
<td align="left">身份认证、登录，验证用户是不是拥有相应的身份</td>
</tr>
<tr>
<td align="left"><code>Authorization</code></td>
<td align="left">授权，即权限验证，验证某个已认证的用户是否拥有某个权限，即判断用户能否进行什么操作，如：验证某个用户已是否拥有某个角色，或者细粒度的验证某个用户对某个资源是否具有某个权限</td>
</tr>
<tr>
<td align="left"><code>Session Manager</code></td>
<td align="left">会话管理，即用户登陆后的第一次会话，没退出前，它的所有信息都在会话中，会话可以是普通的JavaSE环境，也可以是Web环境</td>
</tr>
<tr>
<td align="left"><code>Ctryptography</code></td>
<td align="left">加密，保护数据的安全性，如密码加密存储到数据库中，而不是明文存储</td>
</tr>
<tr>
<td align="left"><code>Web Support</code></td>
<td align="left">Web支持，可以非常容易的集成到Web环境</td>
</tr>
<tr>
<td align="left"><code>Caching</code></td>
<td align="left">缓存，比如用户登录后，其用户信息，拥有的角色、权限不必每次去查，这样可提高效率</td>
</tr>
<tr>
<td align="left"><code>Concurrency </code></td>
<td align="left">Shiro支持多线程应用的并发验证，即，如在一个线程中开启另一个线程，能把权限自动的传播过去</td>
</tr>
<tr>
<td align="left"><code>Testting</code></td>
<td align="left">提供测试支持</td>
</tr>
<tr>
<td align="left"><code>Run As</code></td>
<td align="left">允许一个用户假装为另一个用户（如果他们允许）的身份进行访问</td>
</tr>
<tr>
<td align="left"><code>Remember Me</code></td>
<td align="left">记住我，可在一定时间内记录保持登录的状态。</td>
</tr>
</tbody></table>
<h2 id="1-1-Shiro外部架构"><a href="#1-1-Shiro外部架构" class="headerlink" title="1.1 Shiro外部架构"></a>1.1 Shiro外部架构</h2><p><img src="https://img-blog.csdnimg.cn/8b98d70269ab4488897c3fc637647e73.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"><br><strong>Subject</strong></p>
<blockquote>
<p>Subject是应用代码直接交互的对象，也就是说Shiro的对外API核心就是Subject，Subject代表了当前的用户，这个用户不一定是具体的人，与当前应用交互的任何东西都是Subject，比如网络爬虫，、机器人等，与Subject的所有交互都会委托给SecurityManager；Subject其实是一个门面，SecurityManager才是实际的执行者。</p>
</blockquote>
<p><strong>SecurityManager</strong></p>
<blockquote>
<p>SecurityManager称为安全管理器，即所有与安全有关的操作都会与SecurityManager交互，并且它管理者所有的Subject，所以它称作为Shiro的核心，它负责与Shiro的其他组件进行交互，相当于SpringMVC框架的DispatcherServlet的角色</p>
</blockquote>
<p><strong>Realm</strong></p>
<blockquote>
<p>Shiro从Realm获取安全数据（如用户、角色、权限），就是说SecurityManager要验证用户身份，那么它需要从Realm获取相应的用户进行比较，来确定用户的身份是否合法，也需要从Realm得到用户相应的角色、权限，进行验证用户的操作是否能够进行，可以把Realm看成DataSource</p>
</blockquote>
<h2 id="1-2-Shiro内部架构"><a href="#1-2-Shiro内部架构" class="headerlink" title="1.2 Shiro内部架构"></a>1.2 Shiro内部架构</h2><p><img src="https://img-blog.csdnimg.cn/26796868b61f40deac3baa4803c29c14.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<table>
<thead>
<tr>
<th align="left">模块</th>
<th align="left">描述</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>Subject</code></td>
<td align="left">任何可与应用交互的’用户‘</td>
</tr>
<tr>
<td align="left"><code>Security Manager</code></td>
<td align="left">相当于SpringMVC中的DispatcherServlet；是Shiro的心脏，所有具体的交互都通过SecurityManager进行控制，它管理所有的Subject，且负责进行认证，授权，会话以及缓存的管理。</td>
</tr>
<tr>
<td align="left"><code>Authenticator</code></td>
<td align="left">负责Subject认证，是一个扩展点，可以自定义实现，可以使用认证策略（Authentication Strategy），即什么情况下算用户认证通过了</td>
</tr>
<tr>
<td align="left"><code>Authorizer</code></td>
<td align="left">授权器， 即访问控制器，用来决定主体是否有权限进行相应的操作；即空值着用户能访问应用中的那些功能</td>
</tr>
<tr>
<td align="left"><code>Realm</code></td>
<td align="left">可以由一个或者多个的Realm，可以认为是安全实体数据源，即用于获取安全实体的，可以用JDBC实现，也可以是内存实现等等，由用户提供；所以一般在企业应用中都需要实现自己的realm</td>
</tr>
<tr>
<td align="left"><code>SessionManager</code></td>
<td align="left">管理Session生命周期的组件，而Shiro并不仅仅可以用在Web环境，也可以用在普通的JavaSE环境中</td>
</tr>
<tr>
<td align="left"><code>CacheManager</code></td>
<td align="left">缓存控制器，来管理如用户，角色，权限等缓存的；因为这些数据基本上很少改变，放大缓存中后可以提高访问的性能</td>
</tr>
<tr>
<td align="left"><code>Cryptography</code></td>
<td align="left">密码模块，Shiro提供了常见的加密组件用于密码加密、解密等</td>
</tr>
</tbody></table>
<h1 id="二、Shiro-快速入门"><a href="#二、Shiro-快速入门" class="headerlink" title="二、Shiro 快速入门"></a>二、Shiro 快速入门</h1><hr>
<p>Shiro 官方-快速入门地址：<a target="_blank" rel="noopener" href="https://shiro.apache.org/tutorial.html">点击访问</a></p>
<p>Shiro 1.8 版本下载地址：<a target="_blank" rel="noopener" href="https://www.apache.org/dyn/closer.lua/shiro/1.8.0/shiro-root-1.8.0-source-release.zip">点击访问</a><br><img src="https://img-blog.csdnimg.cn/95847210cb16462a9a890bf920a52b38.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"><br>解压从官方下载的Shiro 1.8.0资源</p>
<p>访问解压后的目录<code>D:\shiro1.8.0\shiro-root-1.8.0\samples\quickstart\src\main\resources</code></p>
<p>通过官方提供的快速入门Maven项目里的配置文件可以实现简单的应用</p>
<p>接下来的内容，部分是参考<strong>官方快速入门文档</strong> ，大部分参考 <strong>视频资料</strong></p>
<h2 id="2-1-使用IDEA创建Maven项目，引入依赖"><a href="#2-1-使用IDEA创建Maven项目，引入依赖" class="headerlink" title="2.1 使用IDEA创建Maven项目，引入依赖"></a>2.1 使用IDEA创建Maven项目，引入依赖</h2><p>贴一个官方快速入门案例的依赖<code>pom.xml</code>，方便做参考</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;UTF-8&quot;</span>?&gt;</span><br><span class="hljs-comment">&lt;!--</span><br><span class="hljs-comment">  ~ Licensed to the Apache Software Foundation (ASF) under one</span><br><span class="hljs-comment">  ~ or more contributor license agreements.  See the NOTICE file</span><br><span class="hljs-comment">  ~ distributed with this work for additional information</span><br><span class="hljs-comment">  ~ regarding copyright ownership.  The ASF licenses this file</span><br><span class="hljs-comment">  ~ to you under the Apache License, Version 2.0 (the</span><br><span class="hljs-comment">  ~ &quot;License&quot;); you may not use this file except in compliance</span><br><span class="hljs-comment">  ~ with the License.  You may obtain a copy of the License at</span><br><span class="hljs-comment">  ~</span><br><span class="hljs-comment">  ~     http://www.apache.org/licenses/LICENSE-2.0</span><br><span class="hljs-comment">  ~</span><br><span class="hljs-comment">  ~ Unless required by applicable law or agreed to in writing,</span><br><span class="hljs-comment">  ~ software distributed under the License is distributed on an</span><br><span class="hljs-comment">  ~ &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span><br><span class="hljs-comment">  ~ KIND, either express or implied.  See the License for the</span><br><span class="hljs-comment">  ~ specific language governing permissions and limitations</span><br><span class="hljs-comment">  ~ under the License.</span><br><span class="hljs-comment">  --&gt;</span><br><span class="hljs-comment">&lt;!--suppress osmorcNonOsgiMavenDependency --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span> <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd&quot;</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.shiro.samples<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>shiro-samples<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.8.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">relativePath</span>&gt;</span>../pom.xml<span class="hljs-tag">&lt;/<span class="hljs-name">relativePath</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>samples-quickstart<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>Apache Shiro :: Samples :: Quick Start<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">packaging</span>&gt;</span>jar<span class="hljs-tag">&lt;/<span class="hljs-name">packaging</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.codehaus.mojo<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>exec-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.6.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">executions</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">execution</span>&gt;</span><br>                        <span class="hljs-tag">&lt;<span class="hljs-name">goals</span>&gt;</span><br>                            <span class="hljs-tag">&lt;<span class="hljs-name">goal</span>&gt;</span>java<span class="hljs-tag">&lt;/<span class="hljs-name">goal</span>&gt;</span><br>                        <span class="hljs-tag">&lt;/<span class="hljs-name">goals</span>&gt;</span><br>                    <span class="hljs-tag">&lt;/<span class="hljs-name">execution</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">executions</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">classpathScope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">classpathScope</span>&gt;</span><br>                    <span class="hljs-tag">&lt;<span class="hljs-name">mainClass</span>&gt;</span>Quickstart<span class="hljs-tag">&lt;/<span class="hljs-name">mainClass</span>&gt;</span><br>                <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span><br><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.shiro<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>shiro-core<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- configure logging --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>jcl-over-slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>runtime<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>slf4j-log4j12<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>runtime<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>runtime<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><br><span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span><br></code></pre></td></tr></table></figure>
<p>测试Demo的依赖 <code>pom.xml</code></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;UTF-8&quot;</span>?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.uni<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>shiro1<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">maven.compiler.source</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">maven.compiler.source</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">maven.compiler.target</span>&gt;</span>8<span class="hljs-tag">&lt;/<span class="hljs-name">maven.compiler.target</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.shiro<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>shiro-core<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.8.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>log4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.17<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>jcl-over-slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.6.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.slf4j<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>slf4j-log4j12<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.6.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span><br></code></pre></td></tr></table></figure>


<h2 id="2-2-配置Shiro"><a href="#2-2-配置Shiro" class="headerlink" title="2.2 配置Shiro"></a>2.2 配置Shiro</h2><p>这里是参考官方案例里的配置</p>
<p>配置日志文件 <code>log4j.properties</code></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-string">log4j.rootLogger=INFO,</span> <span class="hljs-string">stdout</span><br><br><span class="hljs-string">log4j.appender.stdout=org.apache.log4j.ConsoleAppender</span><br><span class="hljs-string">log4j.appender.stdout.layout=org.apache.log4j.PatternLayout</span><br><span class="hljs-string">log4j.appender.stdout.layout.ConversionPattern=%d</span> <span class="hljs-string">%p</span> [<span class="hljs-string">%c</span>] <span class="hljs-bullet">-</span> <span class="hljs-string">%m</span> <span class="hljs-string">%n</span><br><br><span class="hljs-comment"># General Apache libraries</span><br><span class="hljs-string">log4j.logger.org.apache=WARN</span><br><br><span class="hljs-comment"># Spring</span><br><span class="hljs-string">log4j.logger.org.springframework=WARN</span><br><br><span class="hljs-comment"># Default Shiro logging</span><br><span class="hljs-string">log4j.logger.org.apache.shiro=INFO</span><br><br><span class="hljs-comment"># Disable verbose logging</span><br><span class="hljs-string">log4j.logger.org.apache.shiro.util.ThreadContext=WARN</span><br><span class="hljs-string">log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN</span><br></code></pre></td></tr></table></figure>

<p>配置Shiro <code>shiro.ini</code></p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs yml">[<span class="hljs-string">users</span>]<br><span class="hljs-comment"># user &#x27;root&#x27; with password &#x27;secret&#x27; and the &#x27;admin&#x27; role</span><br><span class="hljs-string">root</span> <span class="hljs-string">=</span> <span class="hljs-string">secret,</span> <span class="hljs-string">admin</span><br><span class="hljs-comment"># user &#x27;guest&#x27; with the password &#x27;guest&#x27; and the &#x27;guest&#x27; role</span><br><span class="hljs-string">guest</span> <span class="hljs-string">=</span> <span class="hljs-string">guest,</span> <span class="hljs-string">guest</span><br><span class="hljs-comment"># user &#x27;presidentskroob&#x27; with password &#x27;12345&#x27; (&quot;That&#x27;s the same combination on</span><br><span class="hljs-comment"># my luggage!!!&quot; ;)), and role &#x27;president&#x27;</span><br><span class="hljs-string">presidentskroob</span> <span class="hljs-string">=</span> <span class="hljs-number">12345</span><span class="hljs-string">,</span> <span class="hljs-string">president</span><br><span class="hljs-comment"># user &#x27;darkhelmet&#x27; with password &#x27;ludicrousspeed&#x27; and roles &#x27;darklord&#x27; and &#x27;schwartz&#x27;</span><br><span class="hljs-string">darkhelmet</span> <span class="hljs-string">=</span> <span class="hljs-string">ludicrousspeed,</span> <span class="hljs-string">darklord,</span> <span class="hljs-string">schwartz</span><br><span class="hljs-comment"># user &#x27;lonestarr&#x27; with password &#x27;vespa&#x27; and roles &#x27;goodguy&#x27; and &#x27;schwartz&#x27;</span><br><span class="hljs-string">lonestarr</span> <span class="hljs-string">=</span> <span class="hljs-string">vespa,</span> <span class="hljs-string">goodguy,</span> <span class="hljs-string">schwartz</span><br><br>[<span class="hljs-string">roles</span>]<br><span class="hljs-comment"># &#x27;admin&#x27; role has all permissions, indicated by the wildcard &#x27;*&#x27;</span><br><span class="hljs-string">admin</span> <span class="hljs-string">=</span> <span class="hljs-string">*</span><br><span class="hljs-comment"># The &#x27;schwartz&#x27; role can do anything (*) with any lightsaber:</span><br><span class="hljs-string">schwartz</span> <span class="hljs-string">=</span> <span class="hljs-string">lightsaber:*</span><br><span class="hljs-comment"># The &#x27;goodguy&#x27; role is allowed to &#x27;drive&#x27; (action) the winnebago (type) with</span><br><span class="hljs-comment"># license plate &#x27;eagle5&#x27; (instance specific id)</span><br><span class="hljs-string">goodguy</span> <span class="hljs-string">=</span> <span class="hljs-string">winnebago:drive:eagle5</span><br><br></code></pre></td></tr></table></figure>
<h2 id="2-3-测试运行官方的Quickstart实例"><a href="#2-3-测试运行官方的Quickstart实例" class="headerlink" title="2.3 测试运行官方的Quickstart实例"></a>2.3 测试运行官方的Quickstart实例</h2><p><code>Quickstart.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/*</span><br><span class="hljs-comment"> * Licensed to the Apache Software Foundation (ASF) under one</span><br><span class="hljs-comment"> * or more contributor license agreements.  See the NOTICE file</span><br><span class="hljs-comment"> * distributed with this work for additional information</span><br><span class="hljs-comment"> * regarding copyright ownership.  The ASF licenses this file</span><br><span class="hljs-comment"> * to you under the Apache License, Version 2.0 (the</span><br><span class="hljs-comment"> * &quot;License&quot;); you may not use this file except in compliance</span><br><span class="hljs-comment"> * with the License.  You may obtain a copy of the License at</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> *     http://www.apache.org/licenses/LICENSE-2.0</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * Unless required by applicable law or agreed to in writing,</span><br><span class="hljs-comment"> * software distributed under the License is distributed on an</span><br><span class="hljs-comment"> * &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span><br><span class="hljs-comment"> * KIND, either express or implied.  See the License for the</span><br><span class="hljs-comment"> * specific language governing permissions and limitations</span><br><span class="hljs-comment"> * under the License.</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">import</span> org.apache.shiro.SecurityUtils;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.*;<br><span class="hljs-keyword">import</span> org.apache.shiro.config.IniSecurityManagerFactory;<br><span class="hljs-keyword">import</span> org.apache.shiro.mgt.SecurityManager;<br><span class="hljs-keyword">import</span> org.apache.shiro.session.Session;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.Subject;<br><span class="hljs-keyword">import</span> org.apache.shiro.util.Factory;<br><span class="hljs-keyword">import</span> org.slf4j.Logger;<br><span class="hljs-keyword">import</span> org.slf4j.LoggerFactory;<br><br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Simple Quickstart application showing how to use Shiro&#x27;s API.</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@since</span> 0.9 RC2</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Quickstart</span> &#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">transient</span> <span class="hljs-type">Logger</span> <span class="hljs-variable">log</span> <span class="hljs-operator">=</span> LoggerFactory.getLogger(Quickstart.class);<br><br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br><br>        <span class="hljs-comment">// The easiest way to create a Shiro SecurityManager with configured</span><br>        <span class="hljs-comment">// realms, users, roles and permissions is to use the simple INI config.</span><br>        <span class="hljs-comment">// We&#x27;ll do that by using a factory that can ingest a .ini file and</span><br>        <span class="hljs-comment">// return a SecurityManager instance:</span><br><br>        <span class="hljs-comment">// Use the shiro.ini file at the root of the classpath</span><br>        <span class="hljs-comment">// (file: and url: prefixes load from files and urls respectively):</span><br>        Factory&lt;SecurityManager&gt; factory = <span class="hljs-keyword">new</span> <span class="hljs-title class_">IniSecurityManagerFactory</span>(<span class="hljs-string">&quot;classpath:shiro.ini&quot;</span>);<br>        <span class="hljs-type">SecurityManager</span> <span class="hljs-variable">securityManager</span> <span class="hljs-operator">=</span> factory.getInstance();<br><br>        <span class="hljs-comment">// for this simple example quickstart, make the SecurityManager</span><br>        <span class="hljs-comment">// accessible as a JVM singleton.  Most applications wouldn&#x27;t do this</span><br>        <span class="hljs-comment">// and instead rely on their container configuration or web.xml for</span><br>        <span class="hljs-comment">// webapps.  That is outside the scope of this simple quickstart, so</span><br>        <span class="hljs-comment">// we&#x27;ll just do the bare minimum so you can continue to get a feel</span><br>        <span class="hljs-comment">// for things.</span><br>        SecurityUtils.setSecurityManager(securityManager);<br><br>        <span class="hljs-comment">// Now that a simple Shiro environment is set up, let&#x27;s see what you can do:</span><br><br>        <span class="hljs-comment">// get the currently executing user:</span><br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">currentUser</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br><br>        <span class="hljs-comment">// Do some stuff with a Session (no need for a web or EJB container!!!)</span><br>        <span class="hljs-type">Session</span> <span class="hljs-variable">session</span> <span class="hljs-operator">=</span> currentUser.getSession();<br>        session.setAttribute(<span class="hljs-string">&quot;someKey&quot;</span>, <span class="hljs-string">&quot;aValue&quot;</span>);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">value</span> <span class="hljs-operator">=</span> (String) session.getAttribute(<span class="hljs-string">&quot;someKey&quot;</span>);<br>        <span class="hljs-keyword">if</span> (value.equals(<span class="hljs-string">&quot;aValue&quot;</span>)) &#123;<br>            log.info(<span class="hljs-string">&quot;Retrieved the correct value! [&quot;</span> + value + <span class="hljs-string">&quot;]&quot;</span>);<br>        &#125;<br><br>        <span class="hljs-comment">// let&#x27;s login the current user so we can check against roles and permissions:</span><br>        <span class="hljs-keyword">if</span> (!currentUser.isAuthenticated()) &#123;<br>            <span class="hljs-type">UsernamePasswordToken</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordToken</span>(<span class="hljs-string">&quot;lonestarr&quot;</span>, <span class="hljs-string">&quot;vespa&quot;</span>);<br>            token.setRememberMe(<span class="hljs-literal">true</span>);<br>            <span class="hljs-keyword">try</span> &#123;<br>                currentUser.login(token);<br>            &#125; <span class="hljs-keyword">catch</span> (UnknownAccountException uae) &#123;<br>                log.info(<span class="hljs-string">&quot;There is no user with username of &quot;</span> + token.getPrincipal());<br>            &#125; <span class="hljs-keyword">catch</span> (IncorrectCredentialsException ice) &#123;<br>                log.info(<span class="hljs-string">&quot;Password for account &quot;</span> + token.getPrincipal() + <span class="hljs-string">&quot; was incorrect!&quot;</span>);<br>            &#125; <span class="hljs-keyword">catch</span> (LockedAccountException lae) &#123;<br>                log.info(<span class="hljs-string">&quot;The account for username &quot;</span> + token.getPrincipal() + <span class="hljs-string">&quot; is locked.  &quot;</span> +<br>                        <span class="hljs-string">&quot;Please contact your administrator to unlock it.&quot;</span>);<br>            &#125;<br>            <span class="hljs-comment">// ... catch more exceptions here (maybe custom ones specific to your application?</span><br>            <span class="hljs-keyword">catch</span> (AuthenticationException ae) &#123;<br>                <span class="hljs-comment">//unexpected condition?  error?</span><br>            &#125;<br>        &#125;<br><br>        <span class="hljs-comment">//say who they are:</span><br>        <span class="hljs-comment">//print their identifying principal (in this case, a username):</span><br>        log.info(<span class="hljs-string">&quot;User [&quot;</span> + currentUser.getPrincipal() + <span class="hljs-string">&quot;] logged in successfully.&quot;</span>);<br><br>        <span class="hljs-comment">//test a role:</span><br>        <span class="hljs-keyword">if</span> (currentUser.hasRole(<span class="hljs-string">&quot;schwartz&quot;</span>)) &#123;<br>            log.info(<span class="hljs-string">&quot;May the Schwartz be with you!&quot;</span>);<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            log.info(<span class="hljs-string">&quot;Hello, mere mortal.&quot;</span>);<br>        &#125;<br><br>        <span class="hljs-comment">//test a typed permission (not instance-level)</span><br>        <span class="hljs-keyword">if</span> (currentUser.isPermitted(<span class="hljs-string">&quot;lightsaber:wield&quot;</span>)) &#123;<br>            log.info(<span class="hljs-string">&quot;You may use a lightsaber ring.  Use it wisely.&quot;</span>);<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            log.info(<span class="hljs-string">&quot;Sorry, lightsaber rings are for schwartz masters only.&quot;</span>);<br>        &#125;<br><br>        <span class="hljs-comment">//a (very powerful) Instance Level permission:</span><br>        <span class="hljs-keyword">if</span> (currentUser.isPermitted(<span class="hljs-string">&quot;winnebago:drive:eagle5&quot;</span>)) &#123;<br>            log.info(<span class="hljs-string">&quot;You are permitted to &#x27;drive&#x27; the winnebago with license plate (id) &#x27;eagle5&#x27;.  &quot;</span> +<br>                    <span class="hljs-string">&quot;Here are the keys - have fun!&quot;</span>);<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            log.info(<span class="hljs-string">&quot;Sorry, you aren&#x27;t allowed to drive the &#x27;eagle5&#x27; winnebago!&quot;</span>);<br>        &#125;<br><br>        <span class="hljs-comment">//all done - log out!</span><br>        currentUser.logout();<br><br>        System.exit(<span class="hljs-number">0</span>);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>运行结果：<br><img src="https://img-blog.csdnimg.cn/ad743a6f11c74b9d978a8a4a137a1912.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<h2 id="2-4-官方案例过程梳理"><a href="#2-4-官方案例过程梳理" class="headerlink" title="2.4 官方案例过程梳理"></a>2.4 官方案例过程梳理</h2><blockquote>
<p>第一步，通过配置文件进行初始化</p>
</blockquote>
<p>在官方案例中读取配置文件部分：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java">Factory&lt;SecurityManager&gt; factory = <span class="hljs-keyword">new</span> <span class="hljs-title class_">IniSecurityManagerFactory</span>(<span class="hljs-string">&quot;classpath:shiro.ini&quot;</span>);<br><span class="hljs-type">SecurityManager</span> <span class="hljs-variable">securityManager</span> <span class="hljs-operator">=</span> factory.getInstance();<br>SecurityUtils.setSecurityManager(securityManager);<br></code></pre></td></tr></table></figure>

<p>注：根据IDEA提示，<code>IniSecurityManagerFactory</code>类是过时的，说明有了其他更方便的用法，但这里不会影响使用<br><img src="https://img-blog.csdnimg.cn/a42e7d1c0e7d4ff9b1b3375a0a954226.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<blockquote>
<p>第二步，获取当前用户对象</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">Subject</span> <span class="hljs-variable">currentUser</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br></code></pre></td></tr></table></figure>

<blockquote>
<p>第三步，通过当前用户拿到Session会话</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">Session</span> <span class="hljs-variable">session</span> <span class="hljs-operator">=</span> currentUser.getSession();<br>session.setAttribute(<span class="hljs-string">&quot;someKey&quot;</span>, <span class="hljs-string">&quot;aValue&quot;</span>);<br><span class="hljs-type">String</span> <span class="hljs-variable">value</span> <span class="hljs-operator">=</span> (String) session.getAttribute(<span class="hljs-string">&quot;someKey&quot;</span>);<br><span class="hljs-keyword">if</span> (value.equals(<span class="hljs-string">&quot;aValue&quot;</span>)) &#123;<br>   log.info(<span class="hljs-string">&quot;Retrieved the correct value! [&quot;</span> + value + <span class="hljs-string">&quot;]&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>第四步，进行用户验证</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"> <span class="hljs-keyword">if</span> (!currentUser.isAuthenticated()) &#123;<br>    <span class="hljs-comment">// 生成Token令牌</span><br>    <span class="hljs-type">UsernamePasswordToken</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordToken</span>(<span class="hljs-string">&quot;lonestarr&quot;</span>, <span class="hljs-string">&quot;vespa&quot;</span>);<br>    <span class="hljs-comment">// 设置及记录登录状态</span><br>    token.setRememberMe(<span class="hljs-literal">true</span>);<br>    <span class="hljs-keyword">try</span> &#123;<br>        currentUser.login(token);   <span class="hljs-comment">// 执行登录操作</span><br>    &#125; <span class="hljs-keyword">catch</span> (UnknownAccountException uae) &#123;<br>        log.info(<span class="hljs-string">&quot;There is no user with username of &quot;</span> + token.getPrincipal());<br>    &#125; <span class="hljs-keyword">catch</span> (IncorrectCredentialsException ice) &#123;<br>        log.info(<span class="hljs-string">&quot;Password for account &quot;</span> + token.getPrincipal() + <span class="hljs-string">&quot; was incorrect!&quot;</span>);<br>    &#125; <span class="hljs-keyword">catch</span> (LockedAccountException lae) &#123;<br>        log.info(<span class="hljs-string">&quot;The account for username &quot;</span> + token.getPrincipal() + <span class="hljs-string">&quot; is locked.  &quot;</span> +<br>                <span class="hljs-string">&quot;Please contact your administrator to unlock it.&quot;</span>);<br>    &#125;<br>    <span class="hljs-comment">// ... catch more exceptions here (maybe custom ones specific to your application?</span><br>    <span class="hljs-keyword">catch</span> (AuthenticationException ae) &#123;<br>        <span class="hljs-comment">//unexpected condition?  error?</span><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>第五步，输出当前用户登陆信息，判断用户角色</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java">log.info(<span class="hljs-string">&quot;User [&quot;</span> + currentUser.getPrincipal() + <span class="hljs-string">&quot;] logged in successfully.&quot;</span>);<br><br><span class="hljs-keyword">if</span> (currentUser.hasRole(<span class="hljs-string">&quot;schwartz&quot;</span>)) &#123;<br>    log.info(<span class="hljs-string">&quot;May the Schwartz be with you!&quot;</span>);<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    log.info(<span class="hljs-string">&quot;Hello, mere mortal.&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>第六步，判断当前用户是否有wield权限、eagle5权限</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//test a typed permission (not instance-level)</span><br><span class="hljs-comment">// 检测是否有权限 wield: 粗粒度</span><br><span class="hljs-keyword">if</span> (currentUser.isPermitted(<span class="hljs-string">&quot;lightsaber:wield&quot;</span>)) &#123;<br>    log.info(<span class="hljs-string">&quot;You may use a lightsaber ring.  Use it wisely.&quot;</span>);<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    log.info(<span class="hljs-string">&quot;Sorry, lightsaber rings are for schwartz masters only.&quot;</span>);<br>&#125;<br><br><span class="hljs-comment">//a (very powerful) Instance Level permission:</span><br><span class="hljs-comment">// 检测权限 eagle5: 细粒度</span><br><span class="hljs-keyword">if</span> (currentUser.isPermitted(<span class="hljs-string">&quot;winnebago:drive:eagle5&quot;</span>)) &#123;<br>    log.info(<span class="hljs-string">&quot;You are permitted to &#x27;drive&#x27; the winnebago with license plate (id) &#x27;eagle5&#x27;.  &quot;</span> +<br>            <span class="hljs-string">&quot;Here are the keys - have fun!&quot;</span>);<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    log.info(<span class="hljs-string">&quot;Sorry, you aren&#x27;t allowed to drive the &#x27;eagle5&#x27; winnebago!&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>第七步，注销登陆，结束测试</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java">currentUser.logout();<br>System.exit(<span class="hljs-number">0</span>);<br></code></pre></td></tr></table></figure>

<h1 id="三、Shrio-MDK5"><a href="#三、Shrio-MDK5" class="headerlink" title="三、Shrio MDK5"></a>三、Shrio MDK5</h1><hr>
<p>MDK5算法作用：加密或者签名<br>MDK5算法特点：（1）不可逆（2）若内容相同，无论执行多少次算法，生成的结果始终一致</p>
<p>MDK5算法生成结果：始终是一个16进制、32位长度的字符串</p>
<p>接下来通过一个简单的Demo，应用Shiro整合的MD5加密</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni;<br><span class="hljs-keyword">import</span> org.apache.shiro.crypto.hash.Md5Hash;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestShiroMD5</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>);<br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>);<br>        System.out.println(md5Hash1.toHex());<br>        System.out.println(md5Hash2.toHex());<br>        <span class="hljs-comment">// MD5 + salt</span><br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight llvm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs llvm">e<span class="hljs-number">52805</span>d<span class="hljs-number">8344</span>b<span class="hljs-number">67</span>b<span class="hljs-number">9</span>b<span class="hljs-number">3554</span>d<span class="hljs-number">45</span>f<span class="hljs-number">1</span><span class="hljs-keyword">c</span><span class="hljs-number">8958</span>f<br>e<span class="hljs-number">52805</span>d<span class="hljs-number">8344</span>b<span class="hljs-number">67</span>b<span class="hljs-number">9</span>b<span class="hljs-number">3554</span>d<span class="hljs-number">45</span>f<span class="hljs-number">1</span><span class="hljs-keyword">c</span><span class="hljs-number">8958</span>f<br></code></pre></td></tr></table></figure>

<p>解决MD5算法执行结果一致的问题：设置 <code>salt</code>参数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni;<br><span class="hljs-keyword">import</span> org.apache.shiro.crypto.hash.Md5Hash;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestShiroMD5</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// MD5</span><br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>);<br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>, <span class="hljs-string">&quot;haha&quot;</span>);<br>        System.out.println(md5Hash1.toHex());<br>        System.out.println(md5Hash2.toHex());<br>        <span class="hljs-comment">// MD5 + salt</span><br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>
<p>运行结果：</p>
<figure class="highlight llvm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs llvm">e<span class="hljs-number">52805</span>d<span class="hljs-number">8344</span>b<span class="hljs-number">67</span>b<span class="hljs-number">9</span>b<span class="hljs-number">3554</span>d<span class="hljs-number">45</span>f<span class="hljs-number">1</span><span class="hljs-keyword">c</span><span class="hljs-number">8958</span>f<br><span class="hljs-number">8</span>b<span class="hljs-number">2</span>d<span class="hljs-number">4072</span>ed<span class="hljs-number">1273449708186</span>d<span class="hljs-number">568</span>f<span class="hljs-number">2</span>ff<span class="hljs-number">6</span><br></code></pre></td></tr></table></figure>

<p>除了加<code>salt</code>参数以外，还有一个参数可以提高安全性，即Hash散列次数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni;<br><span class="hljs-keyword">import</span> org.apache.shiro.crypto.hash.Md5Hash;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestShiroMD5</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// MD5</span><br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>);<br>        <span class="hljs-comment">// MD5 + salt</span><br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>, <span class="hljs-string">&quot;haha&quot;</span>);<br>        <span class="hljs-comment">// MD5 + salt + 多次Hash散列</span><br>        <span class="hljs-type">Md5Hash</span> <span class="hljs-variable">md5Hash3</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Md5Hash</span>(<span class="hljs-string">&quot;uni&quot;</span>, <span class="hljs-string">&quot;haha&quot;</span>, <span class="hljs-number">21</span>);<br>        System.out.println(md5Hash1.toHex());<br>        System.out.println(md5Hash2.toHex());<br>        System.out.println(md5Hash3.toHex());<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight llvm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs llvm">e<span class="hljs-number">52805</span>d<span class="hljs-number">8344</span>b<span class="hljs-number">67</span>b<span class="hljs-number">9</span>b<span class="hljs-number">3554</span>d<span class="hljs-number">45</span>f<span class="hljs-number">1</span><span class="hljs-keyword">c</span><span class="hljs-number">8958</span>f<br><span class="hljs-number">8</span>b<span class="hljs-number">2</span>d<span class="hljs-number">4072</span>ed<span class="hljs-number">1273449708186</span>d<span class="hljs-number">568</span>f<span class="hljs-number">2</span>ff<span class="hljs-number">6</span><br><span class="hljs-number">16</span><span class="hljs-keyword">c</span><span class="hljs-number">1</span>bf<span class="hljs-number">99</span>d<span class="hljs-number">04</span><span class="hljs-keyword">c</span><span class="hljs-number">5517</span>f<span class="hljs-number">1</span>ceac<span class="hljs-number">845</span>f<span class="hljs-number">3388</span>d<span class="hljs-number">5</span><br></code></pre></td></tr></table></figure>
<h2 id="3-1-Shiro-认证案例"><a href="#3-1-Shiro-认证案例" class="headerlink" title="3.1 Shiro 认证案例"></a>3.1 Shiro 认证案例</h2><p>经过之前的测试，已经知道了salt为haha，hash21次后的”uni”字符串对应的MD5加密算法后的内容，现写一个简单的案例应用Shiro实现加密验证，项目配置参考本篇之前的快速入门部分</p>
<p><code>UserRealm.java</code> 负责授权与认证</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.md5.realm;<br><br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationToken;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.SimpleAuthenticationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.authz.AuthorizationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.realm.AuthorizingRealm;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.PrincipalCollection;<br><span class="hljs-keyword">import</span> org.apache.shiro.util.ByteSource;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserRealm</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AuthorizingRealm</span> &#123;<br>	<span class="hljs-comment">// 授权，暂时不做测试</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> AuthorizationInfo <span class="hljs-title function_">doGetAuthorizationInfo</span><span class="hljs-params">(PrincipalCollection principals)</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br><br>	<span class="hljs-comment">// 认证</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> AuthenticationInfo <span class="hljs-title function_">doGetAuthenticationInfo</span><span class="hljs-params">(AuthenticationToken token)</span> <span class="hljs-keyword">throws</span> AuthenticationException &#123;<br>        <span class="hljs-comment">// 获取身份信息</span><br>        <span class="hljs-type">String</span> <span class="hljs-variable">principal</span> <span class="hljs-operator">=</span>(String) token.getPrincipal();<br>        <span class="hljs-comment">// 模拟业务层</span><br>        <span class="hljs-keyword">if</span>(<span class="hljs-string">&quot;uni&quot;</span>.equals(principal))&#123;<br>            <span class="hljs-comment">// 参数1: 数据库用户名</span><br>            <span class="hljs-comment">// 参数2: 数据库 md5 + salt 之后的密码</span><br>            <span class="hljs-comment">// 参数3: 注册时的随机salt</span><br>            <span class="hljs-comment">// 参数4: realm的名称</span><br>            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SimpleAuthenticationInfo</span>(<br>                    principal,<br>                    <span class="hljs-string">&quot;16c1bf99d04c5517f1ceac845f3388d5&quot;</span>,<br>                    ByteSource.Util.bytes(<span class="hljs-string">&quot;haha&quot;</span>),<br>                    <span class="hljs-built_in">this</span>.getName());<br>        &#125;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><code>TestUserMd5RealmAuthenicator.java</code> 负责测试Shiro身份认证的结果</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.md5.test;<br><br><span class="hljs-keyword">import</span> com.uni.md5.realm.UserRealm;<br><span class="hljs-keyword">import</span> org.apache.shiro.SecurityUtils;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.IncorrectCredentialsException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.UnknownAccountException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.UsernamePasswordToken;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.credential.HashedCredentialsMatcher;<br><span class="hljs-keyword">import</span> org.apache.shiro.mgt.DefaultSecurityManager;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.Subject;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestUserMd5RealmAuthenicator</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// 安全管理器</span><br>        <span class="hljs-type">DefaultSecurityManager</span> <span class="hljs-variable">manager</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DefaultSecurityManager</span>();<br>        <span class="hljs-comment">// 声明、配置、注入 realm</span><br>        <span class="hljs-type">UserRealm</span> <span class="hljs-variable">realm</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UserRealm</span>();<br>        <span class="hljs-comment">//    设置realm使用hash凭证匹配器</span><br>        <span class="hljs-type">HashedCredentialsMatcher</span> <span class="hljs-variable">credentialsMatcher</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashedCredentialsMatcher</span>();<br>        <span class="hljs-comment">//          指明md5加密算法</span><br>        credentialsMatcher.setHashAlgorithmName(<span class="hljs-string">&quot;md5&quot;</span>);<br>        <span class="hljs-comment">//          指明散列次数</span><br>        credentialsMatcher.setHashIterations(<span class="hljs-number">21</span>);<br>        realm.setCredentialsMatcher(credentialsMatcher);<br>        <span class="hljs-comment">//    注入 realm</span><br>        manager.setRealm(realm);<br>        <span class="hljs-comment">// 将安全管理器注入安全工具</span><br>        SecurityUtils.setSecurityManager(manager);<br><br>        <span class="hljs-comment">// 通过安全工具类获取subject，在web中是从前端传的参数里获取的用户名和密码</span><br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">subject</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br>        <span class="hljs-type">UsernamePasswordToken</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordToken</span>(<span class="hljs-string">&quot;uni&quot;</span>, <span class="hljs-string">&quot;uni&quot;</span>);<br>        <span class="hljs-keyword">try</span> &#123;<br>            subject.login(token);<br>            System.out.println(<span class="hljs-string">&quot;登录成功&quot;</span>);<br>        &#125; <span class="hljs-keyword">catch</span> (UnknownAccountException e) &#123;<br>            e.printStackTrace();<br>            System.out.println(<span class="hljs-string">&quot;用户名错误&quot;</span>);<br>        &#125; <span class="hljs-keyword">catch</span> (IncorrectCredentialsException e)&#123;<br>            e.printStackTrace();<br>            System.out.println(<span class="hljs-string">&quot;密码错误&quot;</span>);<br>        &#125;<br><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">2022</span>-<span class="hljs-number">02</span>-<span class="hljs-number">08</span> <span class="hljs-number">18</span>:<span class="hljs-number">25</span>:<span class="hljs-number">07</span>,<span class="hljs-number">728</span> INFO<span class="hljs-meta"> [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler... </span><br><span class="hljs-meta">登录成功</span><br></code></pre></td></tr></table></figure>

<h2 id="3-2-Shiro-授权案例"><a href="#3-2-Shiro-授权案例" class="headerlink" title="3.2 Shiro 授权案例"></a>3.2 Shiro 授权案例</h2><p><code>UserRealm.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.md5.realm;<br><br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationToken;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.SimpleAuthenticationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.authz.AuthorizationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.authz.SimpleAuthorizationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.realm.AuthorizingRealm;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.PrincipalCollection;<br><span class="hljs-keyword">import</span> org.apache.shiro.util.ByteSource;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Author:      Unirithe/Mr.Chao</span><br><span class="hljs-comment"> * CSDN:        https://blog.csdn.net/Unirithe</span><br><span class="hljs-comment"> * CreatedTime:  2022/2/8 17:53</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserRealm</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AuthorizingRealm</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> AuthorizationInfo <span class="hljs-title function_">doGetAuthorizationInfo</span><span class="hljs-params">(PrincipalCollection principals)</span> &#123;<br>        <span class="hljs-type">String</span> <span class="hljs-variable">primaryPrincipal</span> <span class="hljs-operator">=</span> (String) principals.getPrimaryPrincipal();<br>        <span class="hljs-comment">// 根据身份信息、用户名，获取当前用户的角色信息，以及权限信息</span><br>        <span class="hljs-type">SimpleAuthorizationInfo</span> <span class="hljs-variable">info</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SimpleAuthorizationInfo</span>();<br>        <span class="hljs-comment">// 将数据库中查询角色信息赋值给权限对象</span><br>        info.addRole(<span class="hljs-string">&quot;admin&quot;</span>);<br>        info.addRole(<span class="hljs-string">&quot;user&quot;</span>);<br>        <span class="hljs-comment">// 将数据库中查询权限信息赋值给权限对象</span><br>        info.addStringPermission(<span class="hljs-string">&quot;user:*:01&quot;</span>);<br>        <span class="hljs-keyword">return</span> info;<br>    &#125;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> AuthenticationInfo <span class="hljs-title function_">doGetAuthenticationInfo</span><span class="hljs-params">(AuthenticationToken token)</span> <span class="hljs-keyword">throws</span> AuthenticationException &#123;<br>        <span class="hljs-comment">// 获取身份信息</span><br>        <span class="hljs-type">String</span> <span class="hljs-variable">principal</span> <span class="hljs-operator">=</span>(String) token.getPrincipal();<br>        <span class="hljs-comment">// 模拟业务层</span><br>        <span class="hljs-keyword">if</span>(<span class="hljs-string">&quot;uni&quot;</span>.equals(principal))&#123;<br>            <span class="hljs-comment">// 参数1: 数据库用户名</span><br>            <span class="hljs-comment">// 参数2: 数据库 md5 + salt 之后的密码</span><br>            <span class="hljs-comment">// 参数3: 注册时的随机salt</span><br>            <span class="hljs-comment">// 参数4: realm的名称</span><br>            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SimpleAuthenticationInfo</span>(<br>                    principal,<br>                    <span class="hljs-string">&quot;16c1bf99d04c5517f1ceac845f3388d5&quot;</span>,<br>                    ByteSource.Util.bytes(<span class="hljs-string">&quot;haha&quot;</span>),<br>                    <span class="hljs-built_in">this</span>.getName());<br>        &#125;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><code>TestUserMd5RealmAuthenicator.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.md5.test;<br><br><span class="hljs-keyword">import</span> com.uni.md5.realm.UserRealm;<br><span class="hljs-keyword">import</span> org.apache.shiro.SecurityUtils;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.AuthenticationException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.IncorrectCredentialsException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.UnknownAccountException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.UsernamePasswordToken;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.credential.HashedCredentialsMatcher;<br><span class="hljs-keyword">import</span> org.apache.shiro.mgt.DefaultSecurityManager;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.Subject;<br><br><span class="hljs-keyword">import</span> java.util.Arrays;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TestUserMd5RealmAuthenicator</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// 安全管理器</span><br>        <span class="hljs-type">DefaultSecurityManager</span> <span class="hljs-variable">manager</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DefaultSecurityManager</span>();<br>        <span class="hljs-comment">// 声明、配置、注入 realm</span><br>        <span class="hljs-type">UserRealm</span> <span class="hljs-variable">realm</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UserRealm</span>();<br>        <span class="hljs-comment">//    设置realm使用hash凭证匹配器</span><br>        <span class="hljs-type">HashedCredentialsMatcher</span> <span class="hljs-variable">credentialsMatcher</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashedCredentialsMatcher</span>();<br>        <span class="hljs-comment">//          指明md5加密算法</span><br>        credentialsMatcher.setHashAlgorithmName(<span class="hljs-string">&quot;md5&quot;</span>);<br>        <span class="hljs-comment">//          指明散列次数</span><br>        credentialsMatcher.setHashIterations(<span class="hljs-number">21</span>);<br>        realm.setCredentialsMatcher(credentialsMatcher);<br>        <span class="hljs-comment">//    注入 realm</span><br>        manager.setRealm(realm);<br>        <span class="hljs-comment">// 将安全管理器注入安全工具</span><br>        SecurityUtils.setSecurityManager(manager);<br><br>        <span class="hljs-comment">// 通过安全工具类获取subject</span><br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">subject</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br>        <span class="hljs-type">UsernamePasswordToken</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordToken</span>(<span class="hljs-string">&quot;uni&quot;</span>, <span class="hljs-string">&quot;uni&quot;</span>);<br>        <span class="hljs-keyword">try</span> &#123;<br>            subject.login(token);<br>            System.out.println(<span class="hljs-string">&quot;登录成功&quot;</span>);<br>        &#125; <span class="hljs-keyword">catch</span> (UnknownAccountException e) &#123;<br>            e.printStackTrace();<br>            System.out.println(<span class="hljs-string">&quot;用户名错误&quot;</span>);<br>        &#125; <span class="hljs-keyword">catch</span> (IncorrectCredentialsException e)&#123;<br>            e.printStackTrace();<br>            System.out.println(<span class="hljs-string">&quot;密码错误&quot;</span>);<br>        &#125;<br><br>        <span class="hljs-comment">// 认证用户进行授权</span><br>        <span class="hljs-keyword">if</span>(subject.isAuthenticated())&#123;<br>            <span class="hljs-comment">// 基于角色进行权限控制</span><br>            System.out.println(subject.hasRole(<span class="hljs-string">&quot;admin&quot;</span>));<br>            System.out.println(subject.hasRole(<span class="hljs-string">&quot;user&quot;</span>));<br>            <span class="hljs-comment">// 基于多角色权限控制</span><br>            System.out.println(subject.hasAllRoles(Arrays.asList(<span class="hljs-string">&quot;admin&quot;</span>, <span class="hljs-string">&quot;super&quot;</span>)));<br><br>            <span class="hljs-comment">// 是否有其中一个角色</span><br>            <span class="hljs-type">boolean</span>[] b = subject.hasRoles(Arrays.asList(<span class="hljs-string">&quot;admin&quot;</span>, <span class="hljs-string">&quot;super&quot;</span>, <span class="hljs-string">&quot;user&quot;</span>));<br>            <span class="hljs-keyword">for</span> (<span class="hljs-type">boolean</span> b1 : b) &#123;<br>                System.out.println(b1);<br>            &#125;<br>            System.out.println(<span class="hljs-string">&quot;========================================&quot;</span>);<br>            <span class="hljs-comment">// 基于权限字符串的访问控制， 资源标识符，操作： 资源类型</span><br>            System.out.println(<span class="hljs-string">&quot;权限:&quot;</span> + subject.isPermitted(<span class="hljs-string">&quot;user:update:01&quot;</span>));<br><br>            <span class="hljs-comment">// 分别具有哪些权限</span><br>            <span class="hljs-type">boolean</span>[] permitted = subject.isPermitted(<span class="hljs-string">&quot;user:*:01&quot;</span>, <span class="hljs-string">&quot;commodity:*:*&quot;</span>);<br>            <span class="hljs-keyword">for</span> (<span class="hljs-type">boolean</span> b1 : permitted) &#123;<br>                System.out.println(b1);<br>            &#125;<br><br>            <span class="hljs-comment">// 同时具有哪些权限</span><br>            subject.isPermittedAll(<span class="hljs-string">&quot;user:*:01&quot;</span>, <span class="hljs-string">&quot;product:*&quot;</span>);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="四、SpringBoot整合Shiro-Web-MyBatis-Thymeleaf案例"><a href="#四、SpringBoot整合Shiro-Web-MyBatis-Thymeleaf案例" class="headerlink" title="四、SpringBoot整合Shiro + Web + MyBatis + Thymeleaf案例"></a>四、SpringBoot整合Shiro + Web + MyBatis + Thymeleaf案例</h1><hr>
<p>项目结构：<br>![在这里插入图片描述](<a target="_blank" rel="noopener" href="https://img-blog.csdnimg.cn/f179d2834ebc470cbedcdd38005e6e43.png#">https://img-blog.csdnimg.cn/f179d2834ebc470cbedcdd38005e6e43.png#</a> &#x3D;80%x)</p>
<h2 id="4-1-引入相关依赖"><a href="#4-1-引入相关依赖" class="headerlink" title="4.1 引入相关依赖"></a>4.1 引入相关依赖</h2><p><code>pom.xml</code></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;UTF-8&quot;</span>?&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br><span class="hljs-tag">         <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.6.3<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">relativePath</span>/&gt;</span> <span class="hljs-comment">&lt;!-- lookup parent from repository --&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.uni<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>springboot-shiro<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>0.0.1-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>springboot-shiro<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">description</span>&gt;</span>Demo project for Spring Boot<span class="hljs-tag">&lt;/<span class="hljs-name">description</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">java.version</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">java.version</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-thymeleaf<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- shiro整合spring的依赖 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.shiro<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>shiro-spring<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.6.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- shiro整合Thymeleaf的依赖 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.github.theborakompanioni<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>thymeleaf-extras-shiro<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>        <span class="hljs-comment">&lt;!-- MySQL数据库 + Druid数据源依赖 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>mysql<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mysql-connector-java<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>druid<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.1.9<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-comment">&lt;!-- MyBatis起步依赖 --&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mybatis.spring.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mybatis-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.1.3<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br>        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span><br>            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span><br>        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span><br><br><span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span><br><br></code></pre></td></tr></table></figure>

<h2 id="4-2-配置MyBatis"><a href="#4-2-配置MyBatis" class="headerlink" title="4.2 配置MyBatis"></a>4.2 配置MyBatis</h2><p>配置mybatis的接口映射文件扫描路径<br><code>application.properties</code></p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs properties"><span class="hljs-attr">mybatis.type-aliases-package</span>=<span class="hljs-string">com.uni.pojo</span><br><span class="hljs-attr">mybatis.mapper-locations</span>=<span class="hljs-string">classpath:mapper/*.xml</span><br></code></pre></td></tr></table></figure>

<p>配置数据库 + Druid数据源（许多配置都采用默认的，仅做测试）<br><code>application.yaml</code></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span><br>  <span class="hljs-attr">datasource:</span><br>    <span class="hljs-attr">username:</span> <span class="hljs-string">root</span><br>    <span class="hljs-attr">password:</span> <span class="hljs-string">数据库密码</span><br>    <span class="hljs-attr">url:</span> <span class="hljs-string">jdbc:mysql://localhost:3306/smbms?serverTimezone=UTC</span><br>    <span class="hljs-attr">driver-class-name:</span> <span class="hljs-string">com.mysql.cj.jdbc.Driver</span><br>    <span class="hljs-attr">type:</span> <span class="hljs-string">com.alibaba.druid.pool.DruidDataSource</span><br></code></pre></td></tr></table></figure>
<p>pojo实体类 <code>User.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.pojo;<br><br><span class="hljs-keyword">import</span> lombok.AllArgsConstructor;<br><span class="hljs-keyword">import</span> lombok.Data;<br><span class="hljs-keyword">import</span> lombok.NoArgsConstructor;<br><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-meta">@AllArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span> &#123;<br>    <span class="hljs-keyword">private</span> Integer id;<br>    <span class="hljs-keyword">private</span> String username;<br>    <span class="hljs-keyword">private</span> String password;<br>    <span class="hljs-keyword">private</span> Integer age;<br>&#125;<br></code></pre></td></tr></table></figure>
<p>DAO层接口类 <code>UserMapper.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.mapper;<br><br><span class="hljs-keyword">import</span> com.uni.pojo.User;<br><span class="hljs-keyword">import</span> org.apache.ibatis.annotations.Mapper;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Repository;<br><br><span class="hljs-meta">@Repository</span><br><span class="hljs-meta">@Mapper</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">UserMapper</span> &#123;<br>    <span class="hljs-keyword">public</span> User <span class="hljs-title function_">queryUserByName</span><span class="hljs-params">(String username)</span>;<br><br>&#125;<br></code></pre></td></tr></table></figure>

<p>Mapper映射文件 <code>UserMapper.xml</code>（注：位置在resources资源文件夹的新建文件夹mapper里</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-meta">&lt;?xml version=<span class="hljs-string">&quot;1.0&quot;</span> encoding=<span class="hljs-string">&quot;UTF-8&quot;</span> ?&gt;</span><br><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">mapper</span></span><br><span class="hljs-meta">        <span class="hljs-keyword">PUBLIC</span> <span class="hljs-string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span><br><span class="hljs-meta">        <span class="hljs-string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">mapper</span> <span class="hljs-attr">namespace</span>=<span class="hljs-string">&quot;com.uni.mapper.UserMapper&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;queryUserByName&quot;</span> <span class="hljs-attr">parameterType</span>=<span class="hljs-string">&quot;String&quot;</span> <span class="hljs-attr">resultType</span>=<span class="hljs-string">&quot;User&quot;</span>&gt;</span><br>        SELECT * FROM test_user WHERE username = #&#123;username&#125;<br>    <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">mapper</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>Service层接口类 <code>UserService.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.Service;<br><br><span class="hljs-keyword">import</span> com.uni.pojo.User;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">UserService</span> &#123;<br>    <span class="hljs-keyword">public</span> User <span class="hljs-title function_">queryUserByName</span><span class="hljs-params">(String username)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>Service层接口实现类 <code>UserServiceImpl.java </code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.Service.impl;<br><br><span class="hljs-keyword">import</span> com.uni.Service.UserService;<br><span class="hljs-keyword">import</span> com.uni.mapper.UserMapper;<br><span class="hljs-keyword">import</span> com.uni.pojo.User;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Service;<br><br><span class="hljs-meta">@Service</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">UserService</span> &#123;<br><br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> UserMapper userMapper;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> User <span class="hljs-title function_">queryUserByName</span><span class="hljs-params">(String username)</span> &#123;<br>        <span class="hljs-keyword">return</span> userMapper.queryUserByName(username);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<h2 id="4-3-编写SpringMVC控制层-前端Thymeleaf页面"><a href="#4-3-编写SpringMVC控制层-前端Thymeleaf页面" class="headerlink" title="4.3 编写SpringMVC控制层 + 前端Thymeleaf页面"></a>4.3 编写SpringMVC控制层 + 前端Thymeleaf页面</h2><p>唯一测试的控制层类 <code>MyController.java</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.controller;<br><br><span class="hljs-keyword">import</span> org.apache.shiro.SecurityUtils;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.IncorrectCredentialsException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.UnknownAccountException;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.UsernamePasswordToken;<br><span class="hljs-keyword">import</span> org.apache.shiro.session.Session;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.Subject;<br><span class="hljs-keyword">import</span> org.springframework.stereotype.Controller;<br><span class="hljs-keyword">import</span> org.springframework.ui.Model;<br><span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;<br><span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.PostMapping;<br><span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;<br><span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.ResponseBody;<br><br><span class="hljs-meta">@Controller</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyController</span> &#123;<br><br>    <span class="hljs-meta">@RequestMapping(&#123;&quot;/&quot;, &quot;/index&quot;&#125;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">toIndex</span><span class="hljs-params">(Model model)</span>&#123;<br>        model.addAttribute(<span class="hljs-string">&quot;msg&quot;</span>, <span class="hljs-string">&quot;hello, shiro&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;index&quot;</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@RequestMapping(&quot;/user/add&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">add</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;user/add&quot;</span>;<br>    &#125;<br>    <span class="hljs-meta">@RequestMapping(&quot;/user/update&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">update</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;user/update&quot;</span>;<br>    &#125;<br>    <span class="hljs-meta">@GetMapping(&quot;/toLogin&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">toLogin</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;login&quot;</span>;<br>    &#125;<br><br>    <span class="hljs-meta">@PostMapping(&quot;/login&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">login</span><span class="hljs-params">(String username, String password, Model model)</span>&#123;<br>        <span class="hljs-comment">// 获取当前用户</span><br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">subject</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br>        <span class="hljs-comment">// 封装用户的登录数据</span><br>        <span class="hljs-type">UsernamePasswordToken</span> <span class="hljs-variable">token</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UsernamePasswordToken</span>(username, password);<br>        <span class="hljs-keyword">try</span>&#123;<br>            subject.login(token);   <span class="hljs-comment">// 执行登录的方法，如果没有异常就OK</span><br>            <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;index&quot;</span>;<br>        &#125; <span class="hljs-keyword">catch</span> (UnknownAccountException e) &#123;   <span class="hljs-comment">// 用户名不存在</span><br>            model.addAttribute(<span class="hljs-string">&quot;msg&quot;</span>, <span class="hljs-string">&quot;用户名错误&quot;</span>);<br>            <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;login&quot;</span>;<br>        &#125; <span class="hljs-keyword">catch</span> (IncorrectCredentialsException e)&#123; <span class="hljs-comment">// 密码不存在</span><br>            model.addAttribute(<span class="hljs-string">&quot;msg&quot;</span>, <span class="hljs-string">&quot;密码错误&quot;</span>);<br>            <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;login&quot;</span>;<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-meta">@GetMapping(&quot;/noauth&quot;)</span><br>    <span class="hljs-meta">@ResponseBody</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">unauthorized</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;未经授权无法访问此页面!&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>前端页面主要有四个，如下图：<br><img src="https://img-blog.csdnimg.cn/70c93e12581140cd8e9f53f53dcdce10.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p><code>user/add.html</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>add<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>user/update.html</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>update<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>index.html</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span></span><br><span class="hljs-tag">      <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">&quot;http://www.thymeleaf.org&quot;</span></span><br><span class="hljs-tag">      <span class="hljs-attr">xmlns:shiro</span>=<span class="hljs-string">&quot;http://www.thymeleaf.org/thymeleaf-extras-shiro&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Document<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>首页<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">th:if</span>=<span class="hljs-string">&quot;$&#123;session.loginUser == null&#125;&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;@&#123;/toLogin&#125;&quot;</span>&gt;</span>登录<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;msg&#125;&quot;</span>/&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">shiro:hasPerrmission</span>=<span class="hljs-string">&quot;user:add&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;@&#123;user/add&#125;&quot;</span>&gt;</span>add<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">shiro:hasPerrmission</span>=<span class="hljs-string">&quot;user:update&quot;</span>&gt;</span><br>        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">&quot;@&#123;/user/update&#125;&quot;</span>&gt;</span>update<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>login.html</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">&quot;http://www.thymeleaf.org&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>登陆<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>登陆<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;msg&#125;&quot;</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;color:red&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">th:action</span>=<span class="hljs-string">&quot;@&#123;/login&#125;&quot;</span> <span class="hljs-attr">method</span>=<span class="hljs-string">&quot;post&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>用户名:<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">name</span> = <span class="hljs-string">&quot;username&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>密码:<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">name</span> = <span class="hljs-string">&quot;password&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;submit&quot;</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&quot;登录&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<h2 id="4-4-配置Shiro"><a href="#4-4-配置Shiro" class="headerlink" title="4.4 配置Shiro"></a>4.4 配置Shiro</h2><p><code>ShiroConfig.java</code> SpringBoot集成Shiro框架，可以通过配置类声明几个相关对象的Bean，通过注解注入到Spring容器后就能生效</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.config;<br><br><span class="hljs-keyword">import</span> at.pollux.thymeleaf.shiro.dialect.ShiroDialect;<br><span class="hljs-keyword">import</span> org.apache.shiro.spring.web.ShiroFilterFactoryBean;<br><span class="hljs-keyword">import</span> org.apache.shiro.web.mgt.DefaultWebSecurityManager;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Qualifier;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;<br><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;<br><br><span class="hljs-keyword">import</span> java.util.LinkedHashMap;<br><span class="hljs-keyword">import</span> java.util.Map;<br><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ShiroConfig</span> &#123;<br><br>    <span class="hljs-comment">// 1. ShiroFilterFactoryBean（第三步）</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ShiroFilterFactoryBean <span class="hljs-title function_">getShiroFilterFactoryBean</span><span class="hljs-params">(</span><br><span class="hljs-params">            <span class="hljs-meta">@Qualifier(&quot;securityManager&quot;)</span> DefaultWebSecurityManager defaultWebSecurityManager)</span>&#123;<br>        <span class="hljs-type">ShiroFilterFactoryBean</span> <span class="hljs-variable">bean</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ShiroFilterFactoryBean</span>();<br>        <span class="hljs-comment">// 设置安全管理器</span><br>        bean.setSecurityManager(defaultWebSecurityManager);<br><br>        <span class="hljs-comment">/* 添加 Shiro的内置过滤器</span><br><span class="hljs-comment">        * anon : 无需认证就可以访问</span><br><span class="hljs-comment">        * authc: 必须认证了才能访问</span><br><span class="hljs-comment">        * user: 必须拥有记住我 功能才能访问</span><br><span class="hljs-comment">        * perms: 拥有对某个资源的权限才能访问</span><br><span class="hljs-comment">        * role: 拥有某个角色权限才能访问</span><br><span class="hljs-comment">        * */</span><br>        Map&lt;String, String&gt; filterMap = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedHashMap</span>&lt;&gt;();<br>        <span class="hljs-comment">// 授权, 正常情况下未授权，会跳转到未授权页面</span><br>        filterMap.put(<span class="hljs-string">&quot;/user/add&quot;</span>, <span class="hljs-string">&quot;perms[user:add]&quot;</span>);<br>        filterMap.put(<span class="hljs-string">&quot;/user/*&quot;</span>, <span class="hljs-string">&quot;authc&quot;</span>);<br>        bean.setFilterChainDefinitionMap(filterMap);<br>        <span class="hljs-comment">// 设置登录的请求</span><br>        bean.setLoginUrl(<span class="hljs-string">&quot;/toLogin&quot;</span>);<br>        <span class="hljs-comment">// 未授权页面</span><br>        bean.setUnauthorizedUrl(<span class="hljs-string">&quot;/noauth&quot;</span>);<br>        <span class="hljs-keyword">return</span> bean;<br>    &#125;<br>    <span class="hljs-comment">// 2. DefaultWebSecurityManager（第二步）</span><br>    <span class="hljs-meta">@Bean(name=&quot;securityManager&quot;)</span><br>    <span class="hljs-keyword">public</span> DefaultWebSecurityManager <span class="hljs-title function_">getDefaultWebSecurityManager</span><span class="hljs-params">(<span class="hljs-meta">@Qualifier(&quot;userRealm&quot;)</span> UserRealm userRealm)</span>&#123;<br>        <span class="hljs-type">DefaultWebSecurityManager</span> <span class="hljs-variable">securityManager</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DefaultWebSecurityManager</span>();<br>        <span class="hljs-comment">// 关联 userRealm</span><br>        securityManager.setRealm(userRealm);<br>        <span class="hljs-keyword">return</span> securityManager;<br>    &#125;<br>    <span class="hljs-comment">// 3. 创建 Realm 对象，需自定义类。 （第一步）</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> UserRealm <span class="hljs-title function_">userRealm</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UserRealm</span>();<br>    &#125;<br><br>    <span class="hljs-comment">// 4. 整合 ShiroDialect: 用来整合 shiro thymeleaf</span><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> ShiroDialect <span class="hljs-title function_">getShiroDialect</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ShiroDialect</span>();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><code>UserRealm.java</code> Shiro框架负责认证和授权的重要类，继承于AuthorizingRealm.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.uni.config;<br><br><span class="hljs-keyword">import</span> com.uni.Service.UserService;<br><span class="hljs-keyword">import</span> com.uni.pojo.User;<br><span class="hljs-keyword">import</span> org.apache.shiro.SecurityUtils;<br><span class="hljs-keyword">import</span> org.apache.shiro.authc.*;<br><span class="hljs-keyword">import</span> org.apache.shiro.authz.AuthorizationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.authz.SimpleAuthorizationInfo;<br><span class="hljs-keyword">import</span> org.apache.shiro.realm.AuthorizingRealm;<br><span class="hljs-keyword">import</span> org.apache.shiro.session.Session;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.PrincipalCollection;<br><span class="hljs-keyword">import</span> org.apache.shiro.subject.Subject;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><br><br><span class="hljs-comment">// 自定义的 UserRealm</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">UserRealm</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AuthorizingRealm</span> &#123;<br><br>    <span class="hljs-meta">@Autowired</span><br>    UserService userService;<br>    <span class="hljs-comment">// 授权</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> AuthorizationInfo <span class="hljs-title function_">doGetAuthorizationInfo</span><span class="hljs-params">(PrincipalCollection principalCollection)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;执行了授权方法 =&gt; doGetAuthorizationInfo &quot;</span>);<br>        <span class="hljs-type">SimpleAuthorizationInfo</span> <span class="hljs-variable">info</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SimpleAuthorizationInfo</span>();<br><br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">subject</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br>        <span class="hljs-type">User</span> <span class="hljs-variable">currentUser</span> <span class="hljs-operator">=</span> (User) subject.getPrincipal();      <span class="hljs-comment">// 获取 User 对象</span><br><br>        <span class="hljs-keyword">return</span> info;<br>    &#125;<br>    <span class="hljs-comment">// 认证</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> AuthenticationInfo <span class="hljs-title function_">doGetAuthenticationInfo</span><span class="hljs-params">(AuthenticationToken token)</span> <span class="hljs-keyword">throws</span> AuthenticationException &#123;<br>        System.out.println(<span class="hljs-string">&quot;执行了认证方法 =&gt; doGetAuthenticationInfo&quot;</span>);<br><br>        <span class="hljs-type">Object</span> <span class="hljs-variable">principal</span> <span class="hljs-operator">=</span> token.getPrincipal();<br>        <span class="hljs-type">UsernamePasswordToken</span> <span class="hljs-variable">userToken</span> <span class="hljs-operator">=</span> (UsernamePasswordToken) token;<br>        <span class="hljs-comment">// 连接数据库</span><br>        <span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> userService.queryUserByName(<span class="hljs-string">&quot;uni&quot;</span>);<br>        <span class="hljs-keyword">if</span>(user == <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; <span class="hljs-comment">// UnknownAccountException</span><br>        &#125;<br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">currentSubject</span> <span class="hljs-operator">=</span> SecurityUtils.getSubject();<br>        <span class="hljs-type">Session</span> <span class="hljs-variable">session</span> <span class="hljs-operator">=</span> currentSubject.getSession();<br>        session.setAttribute(<span class="hljs-string">&quot;loginUser&quot;</span>, user);<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SimpleAuthenticationInfo</span>(principal, user.getPassword(), <span class="hljs-string">&quot;&quot;</span>);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>

<h2 id="4-5-运行测试"><a href="#4-5-运行测试" class="headerlink" title="4.5 运行测试"></a>4.5 运行测试</h2><p>启动项目后，访问 <a target="_blank" rel="noopener" href="http://localhost:8080/">hhttp://localhost:8080/</a></p>
<p><img src="https://img-blog.csdnimg.cn/56a440463fac4d26a71aad0e39d29bfc.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>在未登录状态下，点击add或者update都会直接跳转到登陆页面</p>
<p>登陆页面输入密码错误会有错误提示<br><img src="https://img-blog.csdnimg.cn/2c6314af180d4b34ad448877c6c903fc.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"><br>输入数据库里存在的用户登录后，再次跳转到首页<img src="https://img-blog.csdnimg.cn/3b09109466df4895aff090c4355343f0.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>此时可正常访问add和update</p>
<p><img src="https://img-blog.csdnimg.cn/4b440493c2c44d368047a855389a93b2.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<h2 id="4-6-小结"><a href="#4-6-小结" class="headerlink" title="4.6 小结"></a>4.6 小结</h2><p>此案例是参考第一个视频资料的，主要实现了多个框架的简单整合，对于Shiro的简单运用，要点如下：</p>
<ul>
<li>Reaml模块负责于数据库交互，通过token进行参数传递，继承于AuthorizingRealm.java类，对用户实现授权与认证</li>
<li>SecurityManager模块用于设置权限访问的问题，通过注入ShiroFilterFactoryBean配置安全管理器，通过注入DefaultWebSecurityManager关联传递的形参Reaml，还需注入之前Realm模块编写的类</li>
<li>Shrio整合Thymleaf除了要引入依赖以外，还需要在Shiro配置类里注入ShiroDiealect对象的Bean，从而支持在html页面直接使用shiro相关的标签，进行权限判断、角色判断等操作</li>
<li>SpringMVC使用Shiro主要在业务层，而案例中是直接写在控制层，其实在Service层会比较清晰明了，因为它的认证和授权有跟DAO层交互的部分。</li>
</ul>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81/" class="category-chain-item">身份认证</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/Shiro/">#Shiro</a>
      
        <a href="/tags/SpringBoot/">#SpringBoot</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>Shiro 笔记1 Shrio体系结构 MDK5 + salt 加密案例 SpringBoot整合Shiro+SSM+Thymeleaf案例</div>
      <div>http://example.com/2022/02/08/Shiro 笔记1 Shrio体系结构 MDK5 + salt 加密案例 SpringBoot整合Shiro+SSM+Thymeleaf案例/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>John Doe</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年2月8日</div>
        </div>
      
      
      <div class="license-meta-item">
        <div>许可协议</div>
        <div>
          
            
            
              <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
              <span class="hint--top hint--rounded" aria-label="BY - 署名">
                <i class="iconfont icon-by"></i>
              </span>
              </a>
            
          
        </div>
      </div>
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/02/09/Web%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98%20_%20%E8%B4%AD%E7%89%A9%E7%B3%BB%E7%BB%9Fv2.0%20_%20%E5%BC%80%E5%8F%91%E8%AE%B0%E5%BD%95%EF%BC%88%E4%BA%94%EF%BC%89%E4%BD%BF%E7%94%A8base64%E7%BC%96%E7%A0%81%E5%AE%9E%E7%8E%B0%E5%A4%B4%E5%83%8F%E4%BF%AE%E6%94%B9%20_%20%E7%94%A8%E6%88%B7%E4%B8%AA%E4%BA%BA%E4%BF%A1%E6%81%AF%E4%BF%AE%E6%94%B9%20_%20JQuery%E5%8A%A8%E6%80%81%E6%8F%90%E7%A4%BA/" title="Web项目实战 _ 购物系统v2.0 _ 开发记录（五）使用base64编码实现头像修改 _ 用户个人信息修改 _ JQuery动态提示">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Web项目实战 _ 购物系统v2.0 _ 开发记录（五）使用base64编码实现头像修改 _ 用户个人信息修改 _ JQuery动态提示</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/02/06/Web%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98%20_%20%E8%B4%AD%E7%89%A9%E7%B3%BB%E7%BB%9Fv2.0%20_%20%E5%BC%80%E5%8F%91%E8%AE%B0%E5%BD%95%EF%BC%88%E5%85%AD%EF%BC%89%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%E9%A1%B5%E9%9D%A2%20_%20%E6%B8%B8%E5%AE%A2%E8%AE%BF%E9%97%AE%E4%B8%BB%E9%A1%B5%20_%20%E8%BF%90%E7%94%A8Bootstrap4%E8%BD%BB%E9%87%8F%E7%BA%A7%E5%BC%B9%E7%AA%97%E5%AE%9E%E7%8E%B0%E6%8F%90%E7%A4%BA/" title="Web项目实战 _ 购物系统v2.0 _ 开发记录（六）商品详情页面 _ 游客访问主页 _ 运用Bootstrap4轻量级弹窗实现提示">
                        <span class="hidden-mobile">Web项目实战 _ 购物系统v2.0 _ 开发记录（六）商品详情页面 _ 游客访问主页 _ 运用Bootstrap4轻量级弹窗实现提示</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
    </div>
  
  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      headingSelector : CONFIG.toc.headingSelector || 'h1,h2,h3,h4,h5,h6',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      collapseDepth   : CONFIG.toc.collapseDepth || 0,
      scrollSmooth    : true,
      headingsOffset  : -boardTop
    });
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/js/local-search.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
